package com.tools.common.object;

import cn.hutool.core.date.DateTime;
import com.fasterxml.jackson.databind.util.StdDateFormat;
import com.tools.common.exception.ParseRuntimeException;
import com.tools.common.object.string.VerifyKit;
import com.tools.common.thread.Timeunit;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;

/**
 * 日期时间操作工具类
 * 其中包括 JDK 1.8 的日期时间类
 * */
@Note("日期时间操作工具类" +
        "其中包括 JDK 1.8 的日期时间类")
public final class DateKit {

    private DateKit() {}

    @Note("默认的 【日期时间】 格式化字符串")
    public static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    @Note("默认的 【日期】 格式化字符串")
    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
    @Note("默认的 【时间】 格式化字符串")
    public static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";

    @Note("格林威治时间起始日期，即 【1970 年 1 月 1 日】，单独使用 LocalTime 时使用")
    public static final LocalDate START_DATE = LocalDate.of(1970, 1, 1);

    @Note("格林威治时间起始时间，即 【1970 年 1 月 1 日的 00:00:00】，单独使用 LocalDate 时使用")
    public static final LocalTime START_TIME = LocalTime.of(0, 0, 0);

    @Note("默认的【日期时间】 格式化工具对象")
    public static final DateTimeFormatter DEFAULT_DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATETIME_PATTERN);

    @Note("默认的【日期】 格式化工具对象")
    public static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN);

    @Note("默认的【时间】 格式化工具对象")
    public static final DateTimeFormatter DEFAULT_TIME_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN);


    /* *******************************************************************************************
     *
     *          现在日期时间
     *
     * *******************************************************************************************
     * */


    @Note("返回 【yyyy-MM-dd HH:mm:ss】 默认格式的当前时间字符串")
    public static String nowDateTime(){
        return DEFAULT_DATETIME_FORMATTER.format(LocalDateTime.now());
    }


    @Note("返回默认格式的当前日期字符串")
    public static String nowDate() {
        return LocalDate.now().format(DEFAULT_DATE_FORMATTER);
    }

    public static String nowTime() {
        return LocalTime.now().format(DEFAULT_TIME_FORMATTER);
    }


    @Note("用指定的格式化表达式格式化的当前时间字符串")
    public static String now(String formatPattern){
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(formatPattern));
    }

    @Note("用指定的日期时间格式化工具对象来格式化当前日期时间为字符串")
    public static String now(DateTimeFormatter dateTimeFormat){
        return LocalDateTime.now().format(dateTimeFormat);
    }


    @Note("返回指定格式的当前时间字符串")
    public static String now(DateFormat dateFormat){
        return dateFormat.format(new Date());
    }


    /* *******************************************************************************************
     *
     *          格式化为字符串
     *
     * *******************************************************************************************
     * */

    @Note("将 Date 日期时间对象格式化为 【yyyy-MM-dd HH:mm:ss】 的格式")
    public static String format(Date date) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return DEFAULT_DATETIME_FORMATTER.format(dateTime);
    }

    @Note("将 Date 日期时间对象格式化为 【yyyy-MM-dd】 的格式")
    public static String formatDate(Date date) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return DEFAULT_DATE_FORMATTER.format(dateTime.toLocalDate());
    }

    @Note("将 Date 日期时间对象格式化为 【HH:mm:ss.SSS】 的格式")
    public static String formatTime(Date date) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return DEFAULT_TIME_FORMATTER.format(dateTime.toLocalTime());
    }

    @Note("将 Date 日期时间对象格式化为指定的格式")
    public static String format(Date date, DateTimeFormatter formatter) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return formatter.format(dateTime);
    }

    @Note("将 Date 日期时间对象格式化为指定的格式")
    public static String format(Date date, String formatPattern) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern);
        return formatter.format(dateTime);
    }

    @Note("将 Date 日期时间对象格式化为指定的格式")
    public static String format(Date date, DateFormat dateFormat) {
        return dateFormat.format(date);
    }


    @Note("将时间戳格式化为 【yyyy-MM-dd HH:mm:ss】 日期时间字符串")
    public static String format(long timestamp) {
        LocalDateTime localDateTime = localDateTime(timestamp);
        return DEFAULT_DATETIME_FORMATTER.format(localDateTime);
    }

    @Note("将时间戳格式化为 【yyyy-MM-dd】 日期字符串")
    public static String formatDate(long timestamp) {
        LocalDate localDate = localDate(timestamp);
        return DEFAULT_DATE_FORMATTER.format(localDate);
    }

    @Note("将时间戳格式化为 【HH:mm:ss.SSS】 时间字符串")
    public static String formatTime(long timestamp) {
        LocalTime localTime = localTime(timestamp);
        return DEFAULT_TIME_FORMATTER.format(localTime);
    }

    @Note("将时间戳格式化为指定格式的日期时间字符串")
    public static String format(long timestamp, DateTimeFormatter formatter) {
        LocalDateTime localDateTime = localDateTime(timestamp);
        return formatter.format(localDateTime);
    }

    @Note("将时间戳格式化为指定格式的日期时间字符串")
    public static String format(long timestamp, String formatPattern) {
        LocalDateTime localDateTime = localDateTime(timestamp);
        return private_orDefaultFormatter(formatPattern).format(localDateTime);
    }

    @Note("将时间戳格式化为指定格式的日期时间字符串")
    public static String format(long timestamp, DateFormat dateFormat) {
        return dateFormat.format(new Date(timestamp));
    }

    @Note("将日期时间对象格式化为 【yyyy-MM-dd HH:mm:ss】 日期时间字符串")
    public static String format(LocalDateTime dateTime) {
        return DEFAULT_DATETIME_FORMATTER.format(dateTime);
    }


    @Note("将日期对象格式化为 【yyyy-MM-dd】 日期字符串")
    public static String format(LocalDate date) {
        return DEFAULT_DATE_FORMATTER.format(date);
    }

    @Note("将时间对象格式化为 【HH:mm:ss.SSS】 时间字符串")
    public static String format(LocalTime time) {
        return DEFAULT_TIME_FORMATTER.format(time);
    }

    @Note("将日期时间对象格式化为指定格式的日期时间字符串")
    public static String format(LocalDateTime dateTime, DateTimeFormatter formatter) {
        return formatter.format(dateTime);
    }

    @Note("将日期对象格式化为指定格式的日期字符串")
    public static String format(LocalDate date, DateTimeFormatter formatter) {
        return formatter.format(date);
    }

    @Note("将时间对象格式化为指定格式的时间字符串")
    public static String format(LocalTime time, DateTimeFormatter formatter) {
        return formatter.format(time);
    }

    @Note("将日期时间对象格式化为指定格式的日期时间字符串")
    public static String format(LocalDateTime dateTime, String pattern) {
        return DateTimeFormatter.ofPattern(pattern).format(dateTime);
    }

    @Note("将日期对象格式化为指定格式的日期字符串")
    public static String format(LocalDate date, String pattern) {
        return DateTimeFormatter.ofPattern(pattern).format(date);
    }

    @Note("将时间对象格式化为指定格式的时间字符串")
    public static String format(LocalTime time, String pattern) {
        return DateTimeFormatter.ofPattern(pattern).format(time);
    }

    /* *******************************************************************************************
     *
     *          LocalDateTime
     *
     * *******************************************************************************************
     * */

    @Note("获取 ”格林威治日期时间（GMT: 1970-01-01 00:00:00）“ 对象")
    public static LocalDateTime localDateTimeGMT() {
        return LocalDateTime.of(START_DATE, START_TIME);
    }

    @Note("将时间戳转为 JDK 1.8 日期时间对象 LocalDateTime 对象")
    public static LocalDateTime localDateTime(long timestamp) {
        return Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    @Note("将 Date 对象转为 JDK 1.8 日期时间对象 LocalDateTime 对象")
    public static LocalDateTime localDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    @Note("将 JDK 1.8 日期对象 LocalDate 转为日期时间 LocalDateTime 对象")
    public static LocalDateTime localDateTime(LocalDate localDate) {
        return localDate.atStartOfDay();
    }

    @Note("将 JDK 1.8 时间对象 LocalDate 转为日期时间 LocalDateTime 对象")
    public static LocalDateTime localDateTime(LocalTime time) {
        return time.atDate(START_DATE);
    }

    @Note("将 datetime 日期时间字符串转为日期时间 LocalDateTime 对象，格式为 【yyyy-MM-dd HH:mm:ss】")
    public static LocalDateTime localDateTime(String datetime) {
        return LocalDateTime.parse(datetime, DEFAULT_DATETIME_FORMATTER);
    }

    @Note("将 datetime 日期时间字符串转为指定格式的日期时间 LocalDateTime 对象")
    public static LocalDateTime localDateTime(String datetimeString, String formatPattern) {
        return LocalDateTime.parse(datetimeString, DateTimeFormatter.ofPattern(formatPattern));
    }

    @Note("将 datetime 日期时间字符串转为指定格式的日期时间 LocalDateTime 对象")
    public static LocalDateTime localDateTime(String datetimeString, DateTimeFormatter formatter) {
        return LocalDateTime.parse(datetimeString, formatter);
    }

    @Note("将 datetime 日期时间字符串转为指定格式的日期时间 LocalDateTime 对象")
    public static LocalDateTime localDateTime(String datetimeString, DateFormat formatter) {
        try {
            Date date = formatter.parse(datetimeString);
            return localDateTime(date);
        } catch (ParseException e) {
            throw new ParseRuntimeException(e);
        }
    }

    @Note("获取 ”格林威治日期（GMT: 1970-01-01）“ 对象，不包含时间部分")
    public static LocalDate localDateGMT() {
        return START_DATE;
    }

    @Note("将时间戳转为 JDK 1.8 日期对象 LocalDate 对象")
    public static LocalDate localDate(long timestamp) {
        return Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    @Note("将 Date 对象转为 JDK 1.8 日期对象 LocalDate 对象")
    public static LocalDate localDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    @Note("将 JDK 1.8 日期时间对象 LocalDateTime 转为日期 LocalDate 对象")
    public static LocalDate localDate(LocalDateTime dateTime) {
        return dateTime.toLocalDate();
    }

    @Note(" datetime 日期字符串转为日期 LocalDate 对象，格式为 【yyyy-MM-dd】")
    public static LocalDate localDate(String date) {
        return LocalDate.parse(date, DEFAULT_DATE_FORMATTER);
    }

    @Note(" date 日期字符串转为指定格式的日期 LocalDate 对象")
    public static LocalDate localDate(String date, String formatterPattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatterPattern);
        return LocalDate.parse(date, formatter);
    }

    @Note(" date 日期字符串转为指定格式的日期 LocalDate 对象")
    public static LocalDate localDate(String date, DateTimeFormatter formatter) {
        return LocalDate.parse(date, formatter);
    }

    @Note(" date 日期字符串转为指定格式的日期 LocalDate 对象")
    public static LocalDate localDate(String dateString, DateFormat formatter) {
        try {
            Date date = formatter.parse(dateString);
            return localDate(date);
        } catch (ParseException e) {
            throw new ParseRuntimeException(e);
        }
    }


    @Note("获取 ”格林威治（GMT: 1970-01-01）当天日期的现在时间“ 对象，不包含日期部分")
    public static LocalTime localTimeGMT() {
        return START_TIME;
    }

    @Note("将时间戳转为 JDK 1.8 时间对象 LocalTime 对象")
    public static LocalTime localTime(long timestamp) {
        return Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalTime();
    }

    @Note("将 Date 对象转为 JDK 1.8 时间对象 LocalTime 对象")
    public static LocalTime localTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
    }

    @Note("将 JDK 1.8 日期时间对象 LocalDateTime 转为时间 LocalTime 对象")
    public static LocalTime localTime(LocalDateTime dateTime) {
        return dateTime.toLocalTime();
    }

    @Note(" datetime 日期字符串转为时间 LocalTime 对象，格式为 【HH:mm:ss】")
    public static LocalTime localTime(String timeString) {
        return LocalTime.parse(timeString, DEFAULT_TIME_FORMATTER);
    }

    @Note(" datetime 日期字符串转为指定格式的时间 LocalTime 对象")
    public static LocalTime localTime(String timeString, String formatterPattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatterPattern);
        return LocalTime.parse(timeString, formatter);
    }

    @Note(" datetime 日期字符串转为指定格式的时间 LocalTime 对象")
    public static LocalTime localTime(String timeString, DateTimeFormatter formatter) {
        return LocalTime.parse(timeString, formatter);
    }

    @Note(" datetime 日期字符串转为指定格式的时间 LocalTime 对象")
    public static LocalTime localTime(String timeString, DateFormat formatter) {
        try {
            Date date = formatter.parse(timeString);
            return localTime(date);
        } catch (ParseException e) {
            throw new ParseRuntimeException(e);
        }
    }

    @Note("将 JDK 1.8 日期时间对象 LocalDateTime 转为 Date 对象")
    public static Date date(LocalDateTime dateTime) {
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    @Note("将 JDK 1.8 日期对象 LocalDate 转为 Date 对象")
    public static Date date(LocalDate date) {
        ZonedDateTime zonedDateTime = date.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    @Note("将 JDK 1.8 时间对象 LocalTime 转为 Date 对象")
    public static Date date(LocalTime time) {
        LocalDateTime dateTime = time.atDate(START_DATE);
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    @Note("不建议使用，性能较低。将日期时间字符串转为 Date 对象")
    public static Date date(String dateString) {
        return private_handleStringToDate(dateString, 1);
    }

    @Note("不建议使用，性能较低。将日期时间字符串转为 Date 对象")
    public static Date date(String dateString, String formatPattern) {
        return private_handleStringToDate(dateString, DateTimeFormatter.ofPattern(formatPattern), 1);
    }

    @Note("不建议使用，性能较低。将日期时间字符串转为 Date 对象")
    public static Date date(String dateString, DateTimeFormatter formatter) {
        return private_handleStringToDate(dateString, formatter, 1);
    }

    @Note("将 time 时间字符串转为指定格式的 Date 对象")
    public static Date date(String dateString, DateFormat formatter) {
        try {
            return formatter.parse(dateString);
        } catch (ParseException e) {
            throw new ParseRuntimeException(e);
        }
    }

    @Note("将【yyyy-MM-dd HH:mm:ss】日期时间字符串转为 Date 对象")
    public static Date dateByDateTime(String dateTimeString) {
        return dateByDateTime(dateTimeString, DEFAULT_DATETIME_FORMATTER);
    }

    @Note("将【yyyy-MM-dd】日期时间字符串转为 Date 对象")
    public static Date dateByDate(String dateString) {
        return dateByDate(dateString, DEFAULT_DATE_FORMATTER);
    }

    @Note("将【HH:mm:ss】时间字符串转为 Date 对象")
    public static Date dateByTime(String timeString) {
        return dateByTime(timeString, DEFAULT_TIME_FORMATTER);
    }

    @Note("将指定格式的日期时间字符串转为 Date 对象")
    public static Date dateByDateTime(String dateTimeString, String formatterPattern) {
        LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, DateTimeFormatter.ofPattern(formatterPattern));
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    @Note("将指定格式的日期字符串转为 Date 对象")
    public static Date dateByDate(String dateString, String formatterPattern) {
        LocalDate date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern(formatterPattern));
        return Date.from(LocalDateTime.of(date, START_TIME).atZone(ZoneId.systemDefault()).toInstant());
    }

    @Note("将指定格式的时间字符串转为 Date 对象")
    public static Date dateByTime(String timeString, String formatterPattern) {
        LocalTime time = LocalTime.parse(timeString, DateTimeFormatter.ofPattern(formatterPattern));
        return Date.from(LocalDateTime.of(START_DATE, time).atZone(ZoneId.systemDefault()).toInstant());
    }

    @Note("将指定格式的日期时间字符串转为 Date 对象")
    public static Date dateByDateTime(String dateTimeString, DateTimeFormatter formatter) {
        LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    @Note("将指定格式的日期字符串转为 Date 对象")
    public static Date dateByDate(String dateString, DateTimeFormatter formatter) {
        LocalDate date = LocalDate.parse(dateString, formatter);
        return Date.from(LocalDateTime.of(date, START_TIME).atZone(ZoneId.systemDefault()).toInstant());
    }

    @Note("将指定格式的时间字符串转为 Date 对象")
    public static Date dateByTime(String timeString, DateTimeFormatter formatter) {
        LocalTime time = LocalTime.parse(timeString, formatter);
        return Date.from(LocalDateTime.of(START_DATE, time).atZone(ZoneId.systemDefault()).toInstant());
    }


    @Note("返回当前时间的时间戳")
    public static long timestamp(){
        return System.currentTimeMillis();
    }

    @Note("LocalDateTime 转为时间戳")
    public static long timestamp(LocalDateTime localDateTime) {
        return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    @Note("LocalDate 转为时间戳")
    public static long timestamp(LocalDate localDate) {
        return localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
    }

    @Note("LocalTime 转为时间戳")
    public static long timestamp(LocalTime localTime) {
        return localTime.atDate(START_DATE).toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    @Note("【yyyy-MM-dd HH:mm:ss】 日期时间字符串转为时间戳")
    public static long timestampByDateTime(String date) {
        return timestamp(localDateTime(date, DEFAULT_DATETIME_FORMATTER));
    }

    @Note("【yyyy-MM-dd】 日期字符串转为时间戳")
    public static long timestampByDate(String date) {
        return timestamp(localDate(date, DEFAULT_DATE_FORMATTER));
    }

    @Note("【HH:mm:ss】 时间字符串转为时间戳")
    public static long timestampByTime(String date) {
        return timestamp(localTime(date, DEFAULT_TIME_FORMATTER));
    }

    @Note("将指定格式的日期时间字符串转为时间戳")
    public static long timestampByDateTime(String date, String formatterPattern) {
        return timestamp(localDateTime(date, DateTimeFormatter.ofPattern(formatterPattern)));
    }

    @Note("将指定格式的日期字符串转为时间戳")
    public static long timestampByDate(String date, String formatterPattern) {
        return timestamp(localDate(date, DateTimeFormatter.ofPattern(formatterPattern)));
    }

    @Note("将指定格式的时间字符串转为时间戳")
    public static long timestampByTime(String date, String formatterPattern) {
        return timestamp(localTime(date, DateTimeFormatter.ofPattern(formatterPattern)));
    }

    @Note("将指定格式的日期时间字符串转为时间戳")
    public static long timestampByDateTime(String date, DateTimeFormatter formatter) {
        return timestamp(localDateTime(date, formatter));
    }

    @Note("将指定格式的日期字符串转为时间戳")
    public static long timestampByDate(String date, DateTimeFormatter formatter) {
        return timestamp(localDate(date, formatter));
    }

    @Note("将指定格式的时间字符串转为时间戳")
    public static long timestampByTime(String date, DateTimeFormatter formatter) {
        return timestamp(localTime(date, formatter));
    }

    @Note("不建议使用，性能较低。将日期时间字符串转为时间戳")
    public static long timestamp(String date) {
        return private_handleStringToTimestamp(date, 1);
    }

    @Note("不建议使用，性能较低。将日期时间字符串转为时间戳")
    public static long timestamp(String date, String formatPattern) {
        return private_handleStringToTimestamp(date, DateTimeFormatter.ofPattern(formatPattern), 1);
    }

    @Note("不建议使用，性能较低。将日期时间字符串转为时间戳")
    public static long timestamp(String date, DateTimeFormatter formatter) {
        return private_handleStringToTimestamp(date, formatter, 1);
    }

    @Note("将日期时间格式化字符串转为时间戳")
    public static long timestamp(String date, DateFormat dateFormat) {
        if(VerifyKit.isInteger(date)) {
            return Long.parseLong(date);
        }
        try {
            return dateFormat.parse(date).getTime();
        } catch (ParseException e) {
            throw new ParseRuntimeException(e);
        }
    }

    /* *******************************************************************************************
     *
     *      计算和比较
     *
     * *******************************************************************************************
     * */

    @Note("返回 date - unit(time)  的日期时间")
    public static Date before(Date date, long time, Timeunit unit) {
        long dateTime = date.getTime();
        long mill = Timeunit.toMill(time, unit);
        return new Date(dateTime - mill);
    }

    @Note("返回 dateTime - unit(time)  的日期时间")
    public static LocalDateTime before(LocalDateTime dateTime, long time, Timeunit unit) {
        long timestamp = timestamp(dateTime);
        long mill = Timeunit.toMill(time, unit);
        return localDateTime(timestamp - mill);
    }

    @Note("返回 date - unit(time)  的日期时间")
    public static LocalDate before(LocalDate date, long time, Timeunit unit) {
        long timestamp = timestamp(date);
        long mill = Timeunit.toMill(time, unit);
        return localDate(timestamp - mill);
    }

    @Note("返回 time - unit(time)  的时间")
    public static LocalTime before(LocalTime localTime, long time, Timeunit unit) {
        long timestamp = timestamp(localTime);
        long mill = Timeunit.toMill(time, unit);
        return localTime(timestamp - mill);
    }


    @Note("返回 date + unit(time)  的日期时间")
    public static Date after(Date date, long time, Timeunit unit) {
        long dateTime = date.getTime();
        long mill = Timeunit.toMill(time, unit);
        return new Date(dateTime + mill);
    }

    @Note("返回 dateTime + unit(time)  的日期时间")
    public static LocalDateTime after(LocalDateTime dateTime, long time, Timeunit unit) {
        long timestamp = timestamp(dateTime);
        long mill = Timeunit.toMill(time, unit);
        return localDateTime(timestamp + mill);
    }

    @Note("返回 date + unit(time)  的日期时间")
    public static LocalDate after(LocalDate date, long time, Timeunit unit) {
        long timestamp = timestamp(date);
        long mill = Timeunit.toMill(time, unit);
        return localDate(timestamp + mill);
    }

    @Note("返回 time + unit(time)  的时间")
    public static LocalTime after(LocalTime localTime, long time, Timeunit unit) {
        long timestamp = timestamp(localTime);
        long mill = Timeunit.toMill(time, unit);
        return localTime(timestamp + mill);
    }


    @Note("比较时间，d1 op d2")
    public static boolean compare(Date d1, Date d2, ContrastEnum c) {
        return compare(d1.getTime(), d2.getTime(), c);
    }

    @Note("比较时间，d1 op d2")
    public static boolean compare(LocalDateTime d1, LocalDateTime d2, ContrastEnum c) {
        long t1 = timestamp(d1);
        long t2 = timestamp(d2);
        return compare(t1, t2, c);
    }

    @Note("比较日期，d1 op d2")
    public static boolean compare(LocalDate d1, LocalDate d2, ContrastEnum c) {
        long t1 = timestamp(d1);
        long t2 = timestamp(d2);
        return compare(t1, t2, c);
    }

    @Note("比较时间，d1 op d2")
    public static boolean compare(LocalTime d1, LocalTime d2, ContrastEnum c) {
        long t1 = timestamp(d1);
        long t2 = timestamp(d2);
        return compare(t1, t2, c);
    }

    @Note("比较时间戳，d1 op d2")
    public static boolean compare(long time1, long time2, ContrastEnum c) {
        switch (c){
            case EQ: return time1 == time2;
            case GT: return time1 > time2;
            case LT: return time1 < time2;
            case GTE: return time1 >= time2;
            case LTE: return time1 <= time2;
            default: return time1 != time2;
        }
    }

    /* *******************************************************************************************
     *
     *      反射、判断等其他操作
     *
     * *******************************************************************************************
     * */

    @Note("从 DateFormat 对象中获取对应的 pattern 字符串")
    public static String getFormatPattern(DateFormat dateFormat) {
        if(dateFormat instanceof SimpleDateFormat) {
            SimpleDateFormat simple = (SimpleDateFormat) dateFormat;
            return simple.toPattern();
        }
        if(dateFormat instanceof StdDateFormat) {
            StdDateFormat std = (StdDateFormat) dateFormat;
            return std.toPattern();
        }
        return "";
    }

    @Note("判断入参是否是 Date 或者 JDK 1.8 的日期时间的实例")
    public static boolean isDate(Object obj) {
        if(obj == null) return false;
        return (obj instanceof Date) ||
                (obj instanceof TemporalAccessor);
    }

    @Note("判断入参是否是 Date 体系或者 JDK 1.8 日期时间体系下的日期时间类型")
    public static boolean isDateClass(Class<?> objType) {
        if(objType == null) return false;
        return Date.class.isAssignableFrom(objType) ||
                TemporalAccessor.class.isAssignableFrom(objType);
    }


    @Note("将 dateObj 转为指定类型的对象实例返回")
    public static Object toDateEntity(Object dateObj, Class<?> toTargetType, String formatPattern) {
        if(dateObj == null) return null;
        if(toTargetType == null) {
            throw new NullPointerException("实参 toTargetType 为 null，不知道将 dateObj 转为什么类型");
        }
        if(!private_classCanCastToDateEntity(toTargetType)) {
            throw new IllegalArgumentException("无法将 【" + dateObj.getClass().getName() + "】 转为"
                    + toTargetType.getName() + "什么类型");
        }
        if(isDate(dateObj)) {
            Class<?> dateObjClass = dateObj.getClass();
            if(toTargetType.isAssignableFrom(dateObjClass)) {
                return dateObj;
            }
            if(Date.class.equals(dateObjClass)) {
                long time = ((Date) dateObj).getTime();
                return private_timestampToDate(time, toTargetType);
            }
            if(TemporalAccessor.class.isAssignableFrom(dateObjClass)) {
                TemporalAccessor accessor = (TemporalAccessor) dateObj;
                return private_localDateTimeToDate(accessor, toTargetType);
            }
        }
        if(dateObj instanceof Long) {
            if(long.class.equals(toTargetType) || Long.class.isAssignableFrom(toTargetType)) {
                return dateObj;
            }
            long timestamp = (Long) dateObj;
            if(String.class.equals(toTargetType)) {
                return format(timestamp, formatPattern);
            }
            Object o = private_timestampToDate(timestamp, toTargetType);
            if(o == null) {
                throw new ClassCastException("无法将 【" + dateObj.getClass().getName()
                        + "】 转为 【" + toTargetType.getName() + "】类型");
            }
            return o;
        }
        if(dateObj instanceof String) {
            String date = (String) dateObj;
            long timestamp;
            if(VerifyKit.isInteger(date)) {
                timestamp = Long.parseLong(date);
            }
            else {
                DateTimeFormatter formatter = private_orDefaultFormatter(formatPattern);
                timestamp = timestamp(date, formatter);
            }
            if(long.class.equals(toTargetType) || Long.class.isAssignableFrom(toTargetType)) {
                return timestamp;
            }
            Object o = private_timestampToDate(timestamp, toTargetType);
            if(o == null) {
                throw new ClassCastException("无法将 【" + dateObj.getClass().getName()
                        + "】 转为 【" + toTargetType.getName() + "】类型");
            }
            return o;
        }
        throw new ClassCastException("无法将 【" + dateObj.getClass().getName()
                + "】 转为 【" + toTargetType.getName() + "】类型");
    }

    /* *******************************************************************************************
     *
     *      私有逻辑
     *
     * *******************************************************************************************
     * */


    @Note("对入参的 pattern 做个判空替换的操作")
    private static DateTimeFormatter private_orDefaultFormatter(String pattern) {
        return (pattern == null || pattern.isEmpty())
                ? DEFAULT_DATETIME_FORMATTER
                : DateTimeFormatter.ofPattern(pattern);
    }

    @Note("判断 targetType 是否是日期时间对象、或者时间戳、或者字符串")
    private static boolean private_classCanCastToDateEntity(Class<?> targetType) {
        return isDateClass(targetType) ||
                long.class.equals(targetType) ||
                Long.class.equals(targetType) ||
                String.class.equals(targetType);
    }

    @Note("分支判断，将时间戳转为各式各样的日期时间对象")
    private static Object private_timestampToDate(long timestamp, Class<?> targetType) {
        if(Date.class.equals(targetType)) return new Date(timestamp);
        if(java.sql.Date.class.equals(targetType)) return new java.sql.Date(timestamp);
        if(Timestamp.class.equals(targetType)) return new Timestamp(timestamp);
        if(LocalDateTime.class.equals(targetType)) return localDateTime(timestamp);
        if(LocalDate.class.equals(targetType)) return localDate(timestamp);
        if(LocalTime.class.equals(targetType)) return localTime(timestamp);
        if(DateTime.class.equals(targetType)) return new DateTime(timestamp);
        return null;
    }


    @Note("分支判断，将 TemporalAccessor 体系下的日期时间实例，转为 targetType 类型的对象返回")
    private static Object private_localDateTimeToDate(TemporalAccessor accessor, Class<?> targetType) {
        if(targetType.isAssignableFrom(accessor.getClass())) {
            return accessor;
        }
        if(accessor instanceof LocalDateTime) {
            LocalDateTime localDateTime = (LocalDateTime) accessor;
            if(LocalDate.class.equals(targetType)) {
                return localDateTime.toLocalDate();
            }
            if(LocalTime.class.equals(targetType)) {
                return localDateTime.toLocalTime();
            }
            long timestamp = ((LocalDateTime) accessor).toInstant(ZoneOffset.of("+8")).toEpochMilli();
            return private_timestampToDate(timestamp, targetType);
        }
        if(accessor instanceof LocalDate) {
            LocalDate localDate = (LocalDate) accessor;
            if(LocalDateTime.class.equals(targetType)) {
                return localDateTime(localDate);
            }
            if(LocalTime.class.equals(targetType)) {
                return localTime(timestamp(localDate));
            }
            long timestamp = ((LocalDate) accessor).atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
            return private_timestampToDate(timestamp, targetType);
        }
        if(accessor instanceof LocalTime) {
            LocalTime localTime = (LocalTime) accessor;
            if(LocalDateTime.class.equals(targetType)) {
                return localDateTime(localTime);
            }
            if(LocalDate.class.equals(targetType)) {
                return localDate(timestamp(localTime));
            }
            long timestamp = ((LocalTime) accessor).atDate(START_DATE).toInstant(ZoneOffset.of("+8")).toEpochMilli();
            return private_timestampToDate(timestamp, targetType);
        }
        throw new ClassCastException("暂不支持 【" + accessor.getClass().getName() + "】 类型转换为时间戳");
    }


    @Note("使用默认的格式，解析字符串为 java.util.Date 对象")
    private static Date private_handleStringToDate(String time, int i) {
        try {
            if(i == 1) return dateByDateTime(time, DEFAULT_DATETIME_FORMATTER);
            if(i == 2) return dateByDate(time, DEFAULT_DATE_FORMATTER);
            if(i == 3) return dateByTime(time, DEFAULT_TIME_FORMATTER);
        } catch (Exception e) {
            return private_handleStringToDate(time, i + 1);
        }
        throw new ParseRuntimeException("无法解析 【" + time + "】 为 java.util.Date 对象");
    }

    @Note("使用默认的格式，解析字符串转为时间戳")
    private static long private_handleStringToTimestamp(String date, int i) {
        try {
            if(i == 1) return timestamp(date, DEFAULT_DATETIME_FORMATTER);
            if(i == 2) return timestamp(date, DEFAULT_DATE_FORMATTER);
            if(i == 3) return timestamp(date, DEFAULT_TIME_FORMATTER);
        } catch (Exception e) {
            return private_handleStringToTimestamp(date, i + 1);
        }
        throw new IllegalArgumentException("无法将 【" + date + "】 转为时间戳");
    }

    @Note("使用指定的格式，解析字符串为 java.util.Date 对象")
    private static Date private_handleStringToDate(String time, DateTimeFormatter formatter, int i) {
        try {
            if(i == 1) return dateByDateTime(time, formatter);
            if(i == 2) return dateByDate(time, formatter);
            if(i == 3) return dateByTime(time, formatter);
        } catch (Exception e) {
            return private_handleStringToDate(time, formatter, i + 1);
        }
        throw new ParseRuntimeException("无法解析 【" + time + "】 为 java.util.Date 对象");
    }


    @Note("使用指定的格式，解析字符串为时间戳")
    private static long private_handleStringToTimestamp(String date, DateTimeFormatter formatter, int i) {
        try {
            if(i == 1) return timestamp(date, formatter);
            if(i == 2) return timestamp(date, formatter);
            if(i == 3) return timestamp(date, formatter);
        } catch (Exception e) {
            return private_handleStringToTimestamp(date, formatter, i + 1);
        }
        throw new ParseRuntimeException("无法解析 【" + date + "】 为时间戳");
    }


}
